package com.apes.scm.voucher.service.cost;

import com.apes.scm.account.account.model.Cooperation;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryVo;
import com.apes.scm.account.method.Batch;
import com.apes.scm.account.method.BatchMethod;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.model.DeptEnum;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能：返厂订单成本核算
 *
 * @author xul
 * @create 2018-10-18 9:26
 */
@Component
public class PurchaseReturnCostMethod extends AbstractCostMethod {

    public PurchaseReturnCostMethod() {
        this.BusinessTypes = new String[]{BusinessType.PURCHASE_RETURN};
    }

    /**
     * 成本核算/价值评估
     */
    @Override
    public void costing(Voucher voucher) {
        costing(voucher, this::costing, this::createInventoryVoExtend);
    }

    /**
     * 功能：采购退货库存价值评估
     */
    private void costing(CostContext context) {
        Set<InventoryVo> inventoryVos = new HashSet<>();
        InventoryVo inventoryVo = context.getInventoryVo();
        boolean isSureInventories = isSureInventories(inventoryVo); /**是否指定批次**/

        new BatchMethod<Batch>() {

            @Override
            public Iterable wrap() {
                List<InventoryBatch> inventories;
                /**指定批次**/
                if (isSureInventories) {
                    inventories = inventoryVo.getInInventories();
                    if (inventories.stream().filter(inventoryBatch -> !inventoryVo.getCompany().equals(inventoryBatch.getCompany())).count() > 0) {
                        throw new RuntimeException("批次公司与单据公司不一致，请重新确认！");
                    }
                    List<Long> batchNumbers = inventories.stream().map(inventoryBatch -> inventoryBatch.getBatchNumber()).collect(Collectors.toList());
                    inventories = inventoryService.findAllByBatchNumber(batchNumbers, inventory -> inventory.getFrostQty());
                    return inventoryService.wrapBatch(inventories, inventoryVo.getUom(), inventory -> inventory.getFrostQty());
                }
                /**未指定批次**/
                Cooperation cooperation = null;
                if (inventoryVo.getContract() != null) {
                    cooperation = inventoryVo.getContract().getCooperation();
                } else if (inventoryVo.getCooperation() != null) {
                    cooperation = inventoryVo.getCooperation();
                } else {
                    throw new RuntimeException("采购退货合作方式不允许为空！");
                }
                inventories = inventoryService.findByPurchaseReturnInventory(inventoryVo.getCompany(), inventoryVo.getDept(), inventoryVo.getSupplier(), cooperation, inventoryVo.getProduct());
                return inventoryService.wrapBatch(inventories, inventoryVo.getUom(), inventory -> inventory.getBalanceQty() - inventory.getFrostQty());
            }

            @Override
            public void succeed(Batch batch, double increment) {
                InventoryBatch inventoryBatch = (InventoryBatch) batch.getEntity();
                double qty = inventoryVo.getUom().computeQty(increment, inventoryBatch.getUom(), true);
                if (isSureInventories) {
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(),-1 * qty,inventoryBatch.getCompany(),context.getVoucherItem().getVoucher().getInnerBusinessType(),context.getVoucherItem().getVoucher().getInnerBusinessKey(), String.valueOf(context.getVoucherItem().getId()),"采购退货库存价值评估指定批次减少冻结数量");
                } /**指定批次减少冻结数量**/
                inventoryBatch.changeBalanceQty(-1 * qty);
                inventoryBatch.changePurchaseReturnQty(qty);
                inventoryService.save(inventoryBatch);

                InventoryVo vo = new InventoryVo();
                vo.setOutInventoryBatch(inventoryBatch);
                vo.setQty(increment);
                inventoryVos.add(vo);
            }

            @Override
            public void error(double surplus) {
                throw new RuntimeException("商品：["+inventoryVo.getProduct().getId()+"]" + inventoryVo.getProduct().getName() + " 价值库存数量少 " + surplus + inventoryVo.getUom().getName() + "！");
            }
        }.execute(inventoryVo.getQty());

        context.setInventoryVos(inventoryVos);
    }

    private void createInventoryVoExtend(VoucherItem voucherItem, InventoryVo vo) {
        vo.setContract(voucherItem.getVoucher().getContract());
        vo.setCooperation(voucherItem.getVoucher().checkCooperation());
        Dept dept = voucherItem.getVoucher().getDept();
        if (!dept.existDeptType(DeptEnum.PURCHASE)) {
            throw new RuntimeException("业务凭证部门为非采购部门！");
        }
        vo.setDept(dept);
        vo.setSupplier(getSupplier(voucherItem));
        vo.setNoTaxCostPrice(voucherItem.computeExcludedPriceUnit());
        vo.setTaxCostPrice(voucherItem.getPriceUnit());
    }

    private PartyRole getSupplier(VoucherItem voucherItem) {
        /**指定供应商：返厂供应商与批次供应商不同（使用场景）**/
        return voucherItem.getSupplier() != null ? voucherItem.getSupplier() : voucherItem.getVoucher().getPartner();
    }
}
